package com.cch.datageniebackendmaster.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cch.datageniebackendmaster.common.BaseResponse;
import com.cch.datageniebackendmaster.common.Constant;
import com.cch.datageniebackendmaster.mapper.UserMapper;
import com.cch.datageniebackendmaster.model.entity.UserEntity;
import com.cch.datageniebackendmaster.model.enums.ErrorCodeEnum;
import com.cch.datageniebackendmaster.model.request.LoginRequest;
import com.cch.datageniebackendmaster.model.request.RegisterRequest;
import com.cch.datageniebackendmaster.service.UserService;
import com.cch.datageniebackendmaster.util.AuthorityUtil;
import com.cch.datageniebackendmaster.util.ResultUtil;
import com.cch.datageniebackendmaster.util.ThrowUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Objects;

/**
 * <p>
 * 用户 服务实现类
 * </p>
 *
 * @author cch
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements UserService {

    @Override
    public BaseResponse<Boolean> register(RegisterRequest request) {
        // 1、校验
        // 账号格式验证
        ThrowUtil.throwIf(!(request.getUserAccount().length() >= 6 && request.getUserAccount().matches("[a-zA-Z0-9]+"))
                , ErrorCodeEnum.PARAMS_ERROR, "账号格式必须不能使用特殊字符，长度不能少于6位");

        // 两次密码一致
        ThrowUtil.throwIf(!request.getUserPassword().equals(request.getCheckPassword()), ErrorCodeEnum.PARAMS_ERROR, "两次输入的密码不一致");

        // 密码格式验证
        ThrowUtil.throwIf(!request.getUserPassword().matches("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,10}$"),
                ErrorCodeEnum.PARAMS_ERROR, "密码格式必须包含大小写字母和数字的组合，不能使用特殊字符，长度在8-10之间");

        // 账号唯一性验证
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<UserEntity>()
                .eq(UserEntity::getUserAccount, request.getUserAccount());
        ThrowUtil.throwIf(this.count(wrapper) > 0, ErrorCodeEnum.OPERATION_ERROR, "账号已注册");

        // 2、加密
        String safetyPassword = DigestUtils.md5DigestAsHex((request.getUserPassword() + Constant.SALT).getBytes());

        // 3、入库
        UserEntity userEntity = new UserEntity();
        userEntity.setUserAccount(request.getUserAccount());
        userEntity.setUserPassword(safetyPassword);
        ThrowUtil.throwIf(!this.save(userEntity), ErrorCodeEnum.OPERATION_ERROR);
        return ResultUtil.success(true);
    }

    @Override
    public BaseResponse<Boolean> login(LoginRequest request, HttpServletRequest httpServletRequest) {
        // 1、校验
        // httpServletRequest不能为空
        ThrowUtil.throwIf(Objects.isNull(httpServletRequest), ErrorCodeEnum.PARAMS_ERROR);

        // 账号格式验证
        ThrowUtil.throwIf(!(request.getUserAccount().length() >= 6 && request.getUserAccount().matches("[a-zA-Z0-9]+")),
                ErrorCodeEnum.PARAMS_ERROR, "账号格式必须不能使用特殊字符，长度不能少于6位");

        // 密码格式验证
        ThrowUtil.throwIf(!request.getUserPassword().matches("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,10}$"),
                ErrorCodeEnum.PARAMS_ERROR, "密码格式必须包含大小写字母和数字的组合，不能使用特殊字符，长度在8-10之间");

        // 2、加密
        String safetyPassword = DigestUtils.md5DigestAsHex((request.getUserPassword() + Constant.SALT).getBytes());

        // 3、查询
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<UserEntity>()
                .eq(UserEntity::getUserAccount, request.getUserAccount())
                .eq(UserEntity::getUserPassword, safetyPassword);
        UserEntity user = this.getOne(wrapper, false);
        ThrowUtil.throwIf(Objects.isNull(user), ErrorCodeEnum.OPERATION_ERROR, "用户不存在，请检查账号密码是否正确");

        // 4、脱敏
        user.setUserPassword(null);

        // 5、记录登录态
        httpServletRequest.getSession().setAttribute(Constant.USER_LOGIN_SESSION_KEY, user);
        log.info("login: User {} logged in. Session ID: {}", user.getUserAccount(), httpServletRequest.getSession().getId());
        return ResultUtil.success(true);
    }

    @Override
    public BaseResponse<UserEntity> currentUser(HttpServletRequest httpServletRequest) {
        return ResultUtil.success(AuthorityUtil.getLoginUser(httpServletRequest));
    }

    @Override
    public BaseResponse<Boolean> outLogin(HttpServletRequest httpServletRequest) {
        // 1、校验
        // httpServletRequest不能为空
        ThrowUtil.throwIf(Objects.isNull(httpServletRequest), ErrorCodeEnum.PARAMS_ERROR);

        // 2、清除登录态
        HttpSession session = httpServletRequest.getSession(false);
        if (Objects.nonNull(session)) {
            session.invalidate();
            log.info("outLogin: Session invalidated and removed from Redis.");
        } else {
            log.info("outLogin: No session found.");
        }
        return ResultUtil.success(true);
    }

}
